package com.iqiyi.pps.epg.core.service.program;

import com.alibaba.fastjson.JSONObject;
import com.iqiyi.pps.epg.api.model.web.program.TProgramDirector;
import com.iqiyi.pps.epg.api.model.web.program.TProgramDirectorLog;
import com.iqiyi.pps.epg.api.model.web.program.TProgramDirectorLogPage;
import com.iqiyi.pps.epg.api.model.web.program.TProgramDirectorPage;
import com.iqiyi.pps.epg.api.model.web.query.TFilter;
import com.iqiyi.pps.epg.api.model.web.query.TPage;
import com.iqiyi.pps.epg.core.dao.base.Page;
import com.iqiyi.pps.epg.core.dao.base.PropertyFilter;
import com.iqiyi.pps.epg.core.dao.program.ProgramDirectorConfigDao;
import com.iqiyi.pps.epg.core.dao.program.ProgramDirectorDao;
import com.iqiyi.pps.epg.core.dao.program.ProgramDirectorEffectDao;
import com.iqiyi.pps.epg.core.dao.program.ProgramDirectorLogDao;
import com.iqiyi.pps.epg.core.model.program.*;
import com.iqiyi.pps.epg.core.utils.DateTimeUtil;
import com.iqiyi.pps.epg.core.utils.TransUtil;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;


@Service
@Transactional
public class ProgramDirectorServiceImpl implements IProgramDirectorService {
    private static Logger logger = LoggerFactory.getLogger(ProgramDirectorServiceImpl.class);

    private Object lockObj = new Object();
    @Autowired
    private ProgramDirectorDao pdDao;

    @Autowired
    private ProgramDirectorLogDao pdLogDao;

    @Autowired
    private ProgramDirectorEffectDao pdEffectDao;

    @Autowired
    private ProgramDirectorConfigDao pdConfigDao;

    @Autowired
    private ProgramService programService;

    @Override
    public int addProgramDirector(ProgramDirector pd) {
        pdDao.saveOnly(pd);
        return pd.getId();
    }

    @Override
    public long addProgramDirectorLog(ProgramDirectorLog pdLog) {
        pdLogDao.saveOnly(pdLog);
        return pdLog.getId();
    }

    @Override
    public TProgramDirectorLogPage findProgramDirectorLog(TPage page, TFilter filter) {
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        Page<ProgramDirectorLog> dbPage = TransUtil.buildPage(page);
        Page<ProgramDirectorLog> pageData = pdLogDao.findPage(dbPage, filterList);
        List<ProgramDirectorLog> dataList = pageData.getResult();
        TProgramDirectorLogPage tProgramDirectorLogPage = new TProgramDirectorLogPage();
        page.setTotalCount(pageData.getTotalCount());
        tProgramDirectorLogPage.setTPage(page);
        List<TProgramDirectorLog> tProgramDirectorList = transToProgramDirectorLogList(dataList);
        tProgramDirectorLogPage.setResult(tProgramDirectorList);
        return tProgramDirectorLogPage;
    }

    @Override
    public void updateProgramDirector(ProgramDirector pd) {
        pdDao.save(pd);
    }


    @Override
    public void updateCurResourceId(int directorId, int resourceId) {
        String sql = "update ProgramDirector set resourceId = ? where id = ?";
        int executeUpdate = 0;
        synchronized (lockObj) {
            executeUpdate = pdDao.getSession().createQuery(sql).setInteger(0, resourceId).setInteger(1, directorId).executeUpdate();
        }
        logger.info("updateCurResourceId, executeUpdate:" + executeUpdate);
    }

    @Override
    public void updateMainResourceId(int directorId, int mainResourceId) {
        String sql = "update ProgramDirector set mainResourceId = ? where id = ?";
        int executeUpdate = 0;
        synchronized (lockObj) {
            executeUpdate = pdDao.getSession().createQuery(sql).setInteger(0, mainResourceId).setInteger(1, directorId).executeUpdate();
        }
        logger.info("updateMainResourceId, executeUpdate:" + executeUpdate);
    }

    @Override
    public TProgramDirectorPage findProgramDirector(TPage page, TFilter filter, boolean fullMode) {
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        Page<ProgramDirector> dbPage = TransUtil.buildPage(page);
        Page<ProgramDirector> pageData = pdDao.findPage(dbPage, filterList);
        List<ProgramDirector> dataList = pageData.getResult();
        TProgramDirectorPage programDirectorPage = new TProgramDirectorPage();
        page.setTotalCount(pageData.getTotalCount());
        programDirectorPage.setTPage(page);
        List<TProgramDirector> tProgramDirectorList = transToProgramDirectorList(dataList, fullMode);
        programDirectorPage.setResult(tProgramDirectorList);
        return programDirectorPage;
    }

    @Override
    public ProgramDirector getById(int id) {
        return pdDao.get(id);
    }

    @Override
    public ProgramDirector getByProgramQipuId(long programQipuId) {
        List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
        filters.add(new PropertyFilter("EQL_programQipuId", programQipuId + ""));
        filters.add(new PropertyFilter("NEQI_playStatus", "-1"));
        List<ProgramDirector> list = pdDao.find(filters);
        if (list.size() == 0) {
            return null;
        }
        return list.get(list.size() - 1);
    }

    private List<TProgramDirector> transToProgramDirectorList(List<ProgramDirector> dataList, boolean fullMode) {
        List<TProgramDirector> resultList = new ArrayList<>();
        TProgramDirector tProgramDirector = null;
        if (fullMode) {
            for (ProgramDirector tempData : dataList) {
                tProgramDirector = transToTProgramDirector(tempData);
                resultList.add(tProgramDirector);
            }
        } else {
            for (ProgramDirector tempData : dataList) {
                tProgramDirector = transToTProgramDirectorSimple(tempData);
                resultList.add(tProgramDirector);
            }
        }
        return resultList;
    }

    private List<TProgramDirectorLog> transToProgramDirectorLogList(List<ProgramDirectorLog> dataList) {
        List<TProgramDirectorLog> resultList = new ArrayList<>();
        TProgramDirectorLog tProgramDirectorLog = null;
        for (ProgramDirectorLog tempData : dataList) {
            tProgramDirectorLog = transToTProgramDirectorLog(tempData);
            resultList.add(tProgramDirectorLog);
        }
        return resultList;
    }

    @Override
    public TProgramDirector transToTProgramDirectorSimple(ProgramDirector tempData) {
        if (tempData == null) {
            return null;
        }
        TProgramDirector tProgramDirector = new TProgramDirector();
        tProgramDirector.setId(tempData.getId());
        tProgramDirector.setProgramQipuId(tempData.getProgramQipuId());
        tProgramDirector.setProgramName(tempData.getProgramName());
        tProgramDirector.setStartPlayTime(DateTimeUtil.transLongFormat(tempData.getStartPlayTime().getTime()));
        tProgramDirector.setStopPlayTime(DateTimeUtil.transLongFormat(tempData.getStopPlayTime().getTime()));
        tProgramDirector.setPlayStatus(tempData.getPlayStatus());
        tProgramDirector.setResourceId(tempData.getResourceId());
        tProgramDirector.setMainResourceId(tempData.getMainResourceId());
        return tProgramDirector;
    }

    @Override
    public TProgramDirector transToTProgramDirector(ProgramDirector tempData) {
        TProgramDirector tProgramDirector = transToTProgramDirectorSimple(tempData);
        if (tProgramDirector == null) {
            return null;
        }
        tProgramDirector.setAddTime(DateTimeUtil.transLongFormat(tempData.getAddTime().getTime()));
        tProgramDirector.setSource(tempData.getSource());
        tProgramDirector.setDelay(tempData.getDelay());
        if (tempData.getOutputPreviewUrl() != null) {
            tProgramDirector.setOutputPreviewUrl(tempData.getOutputPreviewUrl());

            String[] urls = tempData.getOutputPreviewUrl().split(",");
            if (urls.length >= 1) {
                tProgramDirector.setPreviewStreamUrl(urls[0]);
            }else{
                tProgramDirector.setPreviewStreamUrl("");
            }
        }else{
            tProgramDirector.setPreviewStreamUrl("");
        }
        if (tempData.getOutputStreamType() != null) {
            tProgramDirector.setOutputStreamType(tempData.getOutputStreamType());
        }
        if (tempData.getOutputUrl() != null) {
            tProgramDirector.setOutputUrl(tempData.getOutputUrl());
        }

        tProgramDirector.setImgUrl(getLogoByProgramQipuId(tempData.getProgramQipuId()));

        return tProgramDirector;
    }

    @Override
    public TProgramDirectorLog transToTProgramDirectorLog(ProgramDirectorLog tempData) {
        TProgramDirectorLog tProgramDirectorLog = new TProgramDirectorLog();
        tProgramDirectorLog.setId(tempData.getId());
        tProgramDirectorLog.setDirectorId(tempData.getDirectorId());
        if (tempData.getUser() != null) {
            tProgramDirectorLog.setUser(tempData.getUser());
        }
        tProgramDirectorLog.setType(tempData.getType());
        if (tempData.getDescr() != null) {
            tProgramDirectorLog.setDescr(tempData.getDescr());
        }
        tProgramDirectorLog.setAddTime(DateTimeUtil.transLongFormat(tempData.getAddTime().getTime()));
        return tProgramDirectorLog;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramDirector> findProgramDirectorList(List<Criterion> criterionList) {
        Criteria criteria = pdDao.createCriteria();
        for (Criterion temp : criterionList) {
            criteria.add(temp);
        }
        return pdDao.find(criteria);
    }

    @Override
    public int addProgramDirectorEffect(ProgramDirectorEffect programDirectorEffect) {
        pdEffectDao.saveOnly(programDirectorEffect);
        return programDirectorEffect.getId();
    }

    @Override
    public int editProgramDirectorEffect(ProgramDirectorEffect programDirectorEffect) {
        int result = 0;
        try {
            pdEffectDao.save(programDirectorEffect);
        } catch (Exception e) {
            logger.info("[editProgramDirectorEffect] e = " + e);
            return -1;
        }
        return result;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<ProgramDirectorEffect> getProgramDirectorEffectList(TFilter filter) {
        List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
        return pdEffectDao.find(filterList, Order.desc("id"));
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ProgramDirectorEffect getEffectById(int id) {
        return pdEffectDao.get(id);
    }

    @Override
    public List<ProgramDirectorEffect> createDefaultEffects(int directorId, long programQipuId) {
        List<ProgramDirectorEffect> results = new ArrayList<>();

        // create animation effects
        Criteria animationCriteria = pdConfigDao.createCriteria();

        animationCriteria.add(Restrictions.eq("type", ProgramDirectorConfig.TYPE_EFFECT_ANIMATION));
        animationCriteria.add(Restrictions.eq("status", ProgramDirectorConfig.STATUS_SHOW));
        animationCriteria.addOrder(Order.asc("key"));

        List<ProgramDirectorConfig> effectAnimationList = pdConfigDao.find(animationCriteria);

        for(ProgramDirectorConfig config : effectAnimationList) {
            String params = config.getVal();


            JSONObject jsonObject = null;
            try {
                jsonObject = JSONObject.parseObject(params);
            } catch (Exception e) {
                logger.info("[createDefaultEffects][params={}] e = " + e, params);
                continue;
            }

            ProgramDirectorEffect effect = new ProgramDirectorEffect();
            effect.setDirectorId(directorId);
            effect.setProgramQipuId(programQipuId);
            effect.setType(3);
            effect.setUrl(jsonObject.getString("url"));
            effect.setName(jsonObject.getString("name"));
            effect.setExtraInfo(params);
            effect.setLocation("");
            effect.setStatus(0);
            effect.setOpUser("system");

            int entityId = addProgramDirectorEffect(effect);

            if(entityId > 0) {
                results.add(effect);
            }else{
            }

        }

        // add audio effects
        Criteria audioCriteria = pdConfigDao.createCriteria();
        audioCriteria.add(Restrictions.eq("type", ProgramDirectorConfig.TYPE_EFFECT_AUDIO));
        audioCriteria.add(Restrictions.eq("status", ProgramDirectorConfig.STATUS_SHOW));
        audioCriteria.addOrder(Order.asc("key"));

        List<ProgramDirectorConfig> effectAudioList = pdConfigDao.find(audioCriteria);

        for(ProgramDirectorConfig config : effectAudioList) {
            String params = config.getVal();

            JSONObject jsonObject = null;
            try {
                jsonObject = JSONObject.parseObject(params);
            } catch (Exception e) {
                logger.info("[createDefaultEffects][params={}] e = " + e, params);
                continue;
            }

            ProgramDirectorEffect effect = new ProgramDirectorEffect();
            effect.setDirectorId(directorId);
            effect.setProgramQipuId(programQipuId);
            effect.setType(4);
            effect.setUrl(jsonObject.getString("url"));
            effect.setName(jsonObject.getString("name"));
            effect.setExtraInfo(params);
            effect.setLocation("");
            effect.setStatus(0);
            effect.setOpUser("system");

            int entityId = addProgramDirectorEffect(effect);
            if(entityId > 0) {
                results.add(effect);
            }else{
            }

        }

        //add covers
        String params = "{\"size\":\"{\\\"w\\\":150,\\\"h\\\":100}\"}";
        ProgramDirectorEffect effect = new ProgramDirectorEffect();
        effect.setDirectorId(directorId);
        effect.setProgramQipuId(programQipuId);
        effect.setType(5);
        effect.setUrl("http://jyyunlou7.oss.qiyi.storage:8080/v1/AUTH_becf1c9cf362414992517833e5128e4e/20180103-05/yunpan/20180103/11/88/e009679b12974a11bfedc3638604f7b1.png");
        effect.setName("默认遮标");
        effect.setExtraInfo(params);
        effect.setLocation("");
        effect.setStatus(0);
        effect.setOpUser("system");

        int entityId = addProgramDirectorEffect(effect);
        if(entityId > 0) {
            results.add(effect);
        }else{
        }

        return results;
    }

    private String getLogoByProgramQipuId(long programQipuId) {
        String result = "";
        try {
            ProgramData programData = programService.findProgramDataByQipuId(programQipuId);
            result = programData.getDefaultLogoUrl();
            if(result != null && !result.contains("_145_90")){
                result = result.replace(".jpg","_145_90.jpg");
            }
        } catch (Exception e) {
            logger.info("[getLogoByProgramQipuId] exception = " + e);
        }
        return result;
    }

}
